package gamePlus.server;

import game.Player;
import gamePlus.GameScore;
import gamePlus.server.GameClientSlot.SlotState;

import java.util.LinkedList;
import java.util.Random;

import carddeck.Card;
import carddeck.Rank;
import carddeck.Suit;

import AICore.CPUPlayer;

public class GameUnit {
	protected LinkedList<Player> originalPlayers;
	protected LinkedList<Player> players;
	protected GameServer server;
	protected GameScore gameScore;
	protected RoundUnit roundUnit;
	
	public GameUnit(GameServer server) {
		this.server=server;
		prepareGame();
		gamePrepared();
	}
	
	private void prepareGame() {
		initializePlayers();
		initializeGameScore();
	}

	private void initializePlayers() {
		createPlayers();
		if(server.getServerSettings().randomSlots)
			shufflePlayers();
		linkPlayers();
	}

	private void createPlayers() {
		players = new LinkedList<>();
		originalPlayers = new LinkedList<>();
		GameClientSlot[] slots = server.getGCSlots();
		for(GameClientSlot slot: slots) {
			if(slot.getSlotState()==SlotState.SS_OCCUPIED_HUMAN) {
				Player player = new Player(slot.getPlayerName());
				players.add(player);
				originalPlayers.add(player);
			}
			else if(slot.getSlotState()==SlotState.SS_OCCUPIED_CPU) {
				Player player = new CPUPlayer("CPU#"+(players.size()+1));
				players.add(player);
				originalPlayers.add(player);
			}
		}
	}
	
	private void shufflePlayers() {
		LinkedList<Player> randPlayers = new LinkedList<>();
		while(!players.isEmpty())
			randPlayers.add(players.remove(new Random().nextInt(players.size())));
		players = randPlayers;
	}
	
	private void linkPlayers() {
		Player prevPlayer = players.getLast();
		for(Player thePlayer: players) {
			thePlayer.prevPlayer=prevPlayer;
			prevPlayer.nextPlayer=thePlayer;
			prevPlayer=thePlayer;
		}
	}

	private void initializeGameScore() {
		gameScore = new GameScore(server.getServerSettings(), players);
	}
	
	private void gamePrepared() {
		server.gamePrepared(players);
	}
	
	public void allReadyForRound() {
		roundUnit = new RoundUnit(server, players);
	}

	public void roundEnded(RoundResults results) {
		gameScore.addResult(results);
		if(gameScore.gameEnded(originalPlayers.getFirst().getName()))
			return;
		prepareNewRound();
		
	}
	
	private void prepareNewRound() {
		if(server.getServerSettings().randomSlots) {
			shufflePlayers();
			linkPlayers();
		}
		gamePrepared();
	}

	public void draw(String nameOf) {
		roundUnit.drawCards(nameOf);
	}

	public void playCard(String playerName, LinkedList<Card> cardsToPlay) {
		roundUnit.playCards(playerName, cardsToPlay);
	}

	public void setColor(String playerName, Suit color) {
		roundUnit.selectColor(playerName, color);
	}

	public void setDemand(String playerName, Rank demand) {
		roundUnit.selectDemand(playerName, demand);
	}

	public void playerWaits(String playerName) {
		roundUnit.wait(playerName);
	}

	public void initialPlayCard(String playerName, LinkedList<Card> cardsToPlay) {
		roundUnit.initialPlayCards(playerName, cardsToPlay);
	}
}
